package org.monster.context.core.processor;

import org.monster.context.core.ApplicationFile;
import org.monster.context.core.Constants;
import org.monster.context.core.manager.StringManager;
import org.monster.context.core.parameter.HttpResponse;
import org.monster.context.core.parser.JspParser;
import org.monster.context.core.request.HttpRequest;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * 处理响应
 *
 * @author Monster
 */
public class ProcessResource implements Process {

    /**
     * 日志器
     */
    private static final Logger logger = Logger.getLogger(ProcessResource.class.getName());
    /**
     * 字符串管理器
     */
    private final StringManager sm = StringManager.getManager("org.monster.context.core.processor");
    /**
     * 处理过状态
     */
    private boolean processed = false;

    /**
     * 处理
     *
     * @param request  请求
     * @param response 响应
     */
    @Override
    public boolean process(HttpRequest request, HttpResponse response) {
        String requestURI = request.getRequestURI();
        File file = createFile(request, requestURI);
        if (file != null) {
            if (!file.isFile()) {
                file = new File(file, "index.html");
            }
            if (!file.exists()) {
                response.toNotFound();
                return true;
            }
            try {
                response.setMime("html");
                processHtml(response, file);
                processOther(response, file);
                processJsp(request, response);
            } catch (IOException ex) {
                Logger.getLogger(ProcessResource.class.getName()).log(
                        Level.SEVERE, null, ex);
            }
        } else {
            // 如果没有找到资源文件，打印没有找到的结果给浏览器
            response.toNotFound();
        }
        return true;
    }

    /**
     * 创建 文件
     * 创建请求的资源File对象
     *
     * @param request    请求
     * @param requestURI 请求URI
     * @return 文件
     */
    private File createFile(HttpRequest request, String requestURI) {
        File file;
        String absolutePath = generateContextPath(request);
        file = new File(absolutePath);
        if (file.exists()) {
            return file;
        }
        file = new File(Constants.APPS_PATH, requestURI);
        if (file.exists()) {
            return file;
        }
        return file;
    }

    /**
     * 生成 上下文路径
     * 生成请求的资源文件在服务器的路径
     *
     * @param request 请求
     * @return 应用内容路径
     */
    private String generateContextPath(HttpRequest request) {
        String absolutePath = null;
        String contextPath = request.getContextPath();
        if (contextPath != null) {
            if (contextPath.contains("/")) {
                contextPath = contextPath.substring(1, contextPath.length());
            }
            String contextAbsolutePath = ApplicationFile.getAppContextPath(contextPath);
            String servletPath = request.getServletPath();
            if (servletPath != null) {
                absolutePath = contextAbsolutePath + File.separator
                        + Constants.WEB_CONTENT
                        + servletPath.replace("/", "\\");
            }
        }
        return absolutePath;
    }

    /**
     * 处理 Jsp
     *
     * @param request  请求
     * @param response 响应
     */
    private void processJsp(HttpRequest request, HttpResponse response) {
        if (response.getMime().equals("jsp")) {
            ProcessJsp projectJsp = new ProcessJsp(new JspParser());
            projectJsp.process(request, response);
        }
    }

    /**
     * 处理 HTML
     *
     * @param response 响应
     * @param file     文件
     * @throws IOException 输入输出异常
     */
    private void processHtml(HttpResponse response, File file) throws IOException {
        if (response.getMime().equalsIgnoreCase("html")) {
            response.sendResource(file);
            processed = true;
        }
    }

    /**
     * 处理 其他
     *
     * @param response 响应
     * @param file     文件
     * @throws IOException 输入输出异常
     */
    private void processOther(HttpResponse response, File file) throws IOException {
        if (file != null && file.isFile() && file.exists() && !processed) {
            try {
                FileInputStream fis = new FileInputStream(file);
                byte buf[] = new byte[fis.available()];
                int len = fis.read(buf);
                response.setContentLength(len);
                response.sendHeaders();
                response.sendStream(buf);
                fis.close();
            } catch (IOException e) {
                logger.log(Level.INFO,
                        sm.getString("ResourceProcessor.processOther"));
            }
            processed = false;
        }
    }
}
